package uvsq.acsis.projects.xml.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XmlHelper {

	public static String addWrap(String xml, String wrap){
		
		return "<" + wrap + ">" + xml + "</" + wrap + ">";
	}
	
	public static NodeList removeWrap(String xml){
		
		Document doc = getDocument(xml);
		if(doc != null){
			Node root = doc.getDocumentElement();
			return root.getChildNodes();
		}
		  
		return null;
	}
	
	public static Document getDocument(String xml){
		return readXml(xml);
	}
	
	public static Document getDocument(File xml){
		return readXml(xml);
	}
	
	private static Document readXml(Object xml){
		
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		Document doc = null;
		
		try {
			
			db = dbf.newDocumentBuilder();
			
			if(xml instanceof String){
				doc = db.parse(new ByteArrayInputStream(((String) xml).getBytes()));
			}
			else if(xml instanceof File){
				doc = db.parse((File) xml);
			}
			
		} catch (ParserConfigurationException e1) {
			e1.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return doc;
	}
	
	public static void appendXmlFile(String file, String newDate){
		
		Document doc = getDocument(new File(file));
		Node root = doc.getDocumentElement();
		
		NodeList nodes = removeWrap(newDate);
		
		for(int i = 0; i < nodes.getLength(); i++)
			root.appendChild(doc.importNode(nodes.item(i), true));
		
		saveXmlFile(file, root);
	}
	
	public static void saveXmlFile(String fileToSave, Document data){
		saveXml(fileToSave, data);
	}

	public static void saveXmlFile(String fileToSave, String data){
		saveXml(fileToSave, data);
	}
	
	public static void saveXmlFile(String fileToSave, Node data){
		saveXml(fileToSave, data);
	}
	
	private static void saveXml(String fileToSave, Object o){
		TransformerFactory tfactory = TransformerFactory.newInstance();  
        Transformer transformeur;
		
        try {
			transformeur = tfactory.newTransformer();
			Source entry = null;
			
			if(o instanceof String){
				String os = (String) o;
				entry = new DOMSource(getDocument(os));
			}
			else {
				if (o instanceof Document) {
					Document od = (Document) o;
					entry = new DOMSource(od);
				} 
				else {
					Node on = (Node) o;
					entry = new DOMSource(on);
				}
			}
			
			Result out = new StreamResult(new File(fileToSave));  
			transformeur.transform(entry, out);
			
        } catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}
	
	public static String nodeToString(Node node) {
		 StringWriter sw = new StringWriter();
		 try {
		   Transformer t = TransformerFactory.newInstance().newTransformer();
		   t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
		   t.transform(new DOMSource(node), new StreamResult(sw));
		 } catch (TransformerException te) {
		   System.out.println("nodeToString Transformer Exception");
		   return null;
		 }
		 return sw.toString();
	}
	
	public static String nodeToString(NodeList nodeList) {
		 StringWriter sw = new StringWriter();
		 StringBuffer sb = new StringBuffer();
		 
		 try {
		   Transformer t = TransformerFactory.newInstance().newTransformer();
		   t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
		   
		   for(int i = 1; i < nodeList.getLength(); i++){
			   t.transform(new DOMSource(nodeList.item(i)), new StreamResult(sw));
			   sb.append(sw.toString());
		   }
		   
		 } catch (TransformerException te) {
		   System.out.println("nodeListToString Transformer Exception");
		 }
		 
		 return sb.toString();
	}
}
